package com.l9lou.creeper.server;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 *主要用于配置server的端口信息，同时集合各种服务
 *
 *
 * User: eric
 * Date: 11-7-16
 * Time: 下午6:37
 */
public class Server {

    private int port;
    private boolean started = false;
    private List<ChannelUpstreamHandler> upstreamHandlers;
    private List<ChannelDownstreamHandler> downstreamHandlers;

    public void start(){
        if(this.started){
            throw new IllegalStateException("The Server has already been started");
        }
        ServerBootstrap serverBootstrap = newServerBootstrap();
        serverBootstrap.setPipelineFactory(newChannelPipelineFactory());
        prepareServerSocketOptions(serverBootstrap);
        serverBootstrap.bind(new InetSocketAddress(port));
        this.started = true;
    }

    private ServerBootstrap newServerBootstrap() {
        Executor boss = Executors.newSingleThreadExecutor();
        Executor works = Executors.newCachedThreadPool();
        final ChannelFactory factory = new NioClientSocketChannelFactory(boss, works);
        return new ServerBootstrap(factory);
    }

    private ChannelPipelineFactory newChannelPipelineFactory(){
        return new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline pipeline = Channels.pipeline();
                addHandlers(pipeline, upstreamHandlers);
                addHandlers(pipeline, downstreamHandlers);
                return pipeline;
            }
        };
    }

    private void prepareServerSocketOptions(ServerBootstrap serverBootstrap) {
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("child.keepAlive", true);
        options.put("child.tcpNoDelay", true);
        options.put("reuseAddress", true);
        serverBootstrap.setOptions(options);
    }

    private void addHandlers(ChannelPipeline pipeline, List<? extends ChannelHandler> handlers) {
        for(ChannelHandler handler : handlers){
            pipeline.addLast(handler.getClass().getName(), handler);
        }
    }


    public void setPort(int port) {
        this.port = port;
    }

    public void setUpstreamHandlers(List<ChannelUpstreamHandler> upstreamHandlers) {
        this.upstreamHandlers = upstreamHandlers;
    }

    public void setDownstreamHandlers(List<ChannelDownstreamHandler> downstreamHandlers) {
        this.downstreamHandlers = downstreamHandlers;
    }
}
